package cn.com.dcsgo.advice;

import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * LogAdvice
 *
 * 配置增强(通知)方法
 * 前置 @Before
 * 后置 @AfterReturning
 * 异常 @AfterThrowing
 * 最后 @After
 * 环绕 @Around
 * try{
 *   前置
 *   目标
 *   后置
 * }catch(){
 *    异常
 * }finally{
 *    最后
 * }
 *
 * @author Dcsgo
 * @since 2025/2/6 11:38
 */
//@Aspect //表示这是一个切面
//@Component //spring aop 切面得被装配到IoC容器
public class LogAdvice {

    /**
     * 切点表达式 要连接那些切点(增强哪些类的哪些方法)
     * execution(访问修饰符 返回类型 类全限定名.方法名(参数列表))
     * 访问修饰符与返回类型不做要求(任意) 可用星号代替(两者要么都指定要么都不指定,类似 * String 是不合法的)
     * 类全权限定名中的包名 可以用通配符，* 代表单层包路径 .. 代表任意层包路径，但..不能写在开头
     *              类名 也可以用通配符，* 表示任意字符或字符串
     * 方法名同类名
     *   参数列表
     *   无参()
     *   指定具体参数类型(String,int)
     *   模糊匹配 .. 匹配任意(数量、类型)参数。(..)->任意参数的方法 (String,..)第一个参数是String类型的方法
     */
    @Before("execution(* cn.com.dcsgo.service.impl.*.*(..))")
    public void start() {
        System.out.println("方法开始了");
    }

    @AfterReturning("execution(* cn.com.dcsgo.service.impl.*.*(..))")
    public void after() {
        System.out.println("方法返回了");
    }

    @AfterThrowing("execution(* cn.com.dcsgo.service.impl.*.*(..))")
    public void error() {
        System.out.println("方法报错了");
    }

    /*
    1.查询某包某类下，访问修饰符是公有的，返回值是int的全部方法
    execution(public int cn.com.dcsgo.demo.packages.DemoClass.*(..))
    2.查询某包下类中第一个参数是String的方法
    execution(* cn.com.dcsgo.demo.packages.*(String,..))
    3.查询全部包下，无参数的方法
    execution(* *..*.*())
    4.查询com包下，以int参数类型结尾的方法
    execution(* com..*.*(..,int))
    5.查询指定包下，Service开头的类并且是私有方法返回类型是int的无参方法
    execution(private int cn.com.dcsgo.demo.packages.Service*.*())
     */
}
